using System;
using System.Collections;
using EnvDTE;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using VSSDKAssist.Assets.Helpers;
using VSSDKAssist.Assets.ValueProviders.Base;

namespace VSShellAssist.Recipes.Common.ValueProviders
{
	/// <summary>
	/// Value provider for the VSPackage Class
	/// </summary>
	public class VSPackageCodeClassValueProvider : ValueProviderBase
	{
		#region Public Implementation

		/// <summary>
		/// Contains code that will be called when recipe execution begins. This is the first method in the lifecycle.
		/// </summary>
		/// <param name="currentValue">An <see cref="T:System.Object"/> that contains the current value of the argument.</param>
		/// <param name="newValue">When this method returns, contains an <see cref="T:System.Object"/> that contains
		/// the new value of the argument, if the returned value
		/// of the method is <see langword="true"/>. Otherwise, it is ignored.</param>
		/// <returns>
		/// 	<see langword="true"/> if the argument value should be replaced with
		/// the value in <paramref name="newValue"/>; otherwise, <see langword="false"/>.
		/// </returns>
		/// <remarks>By default, always returns <see langword="false"/>, unless overriden by a derived class.</remarks>
		public override bool OnBeginRecipe(object currentValue, out object newValue)
		{
			newValue = null;

			if((currentValue == null) && (this.ExecutionStage != Stage.OnBeforeActions))
			{
				IVsHierarchy hierarchy = VSIPHelper.GetCurrentSelection(this.Site as IServiceProvider);
				Project project = null;

				object selectedObject;

				ErrorHandler.ThrowOnFailure(
					hierarchy.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ExtObject, out selectedObject));

				project = (Project)selectedObject;

				if(project != null)
				{
					TypeDiscoveryHelper typeDiscoveryHelper = new TypeDiscoveryHelper(this.Site as IServiceProvider);
					ICollection types = typeDiscoveryHelper.GetTypes(typeof(Package));

					foreach(Type type in types)
					{
						if(type.Assembly.ManifestModule.Name.Equals(
							project.Properties.Item("OutputFileName").Value.ToString(), StringComparison.OrdinalIgnoreCase))
						{
							CodeClass packageClass =
								FileCodeModelHelper.FindCodeElementByTypeName(
								project, type.FullName, vsCMElement.vsCMElementClass) as CodeClass;

							newValue = packageClass;
							return true;
						}
					}
				}
			}

			return false;
		}
		#endregion
	}
}